#pragma once

#include <QHeaderView>
#include <QLabel>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTimer>
#include <QWidget>
#include <map>
#include <vector>

#include "../widgets.h"

const int DataIdRole = Qt::UserRole + 1;
const int PrefixImgRole = Qt::UserRole + 2;
const int PostfixImgRole = Qt::UserRole + 3;
const int PrefixTipRole = Qt::UserRole + 4;
const int PostfixTipRole = Qt::UserRole + 5;
const int HeaderSortRole = Qt::UserRole + 6;
const int BrokerIdRole = Qt::UserRole + 7;
const int HolidayTypeRole = Qt::UserRole + 8;
const int HolidayNumberRole = Qt::UserRole + 9;
const int MaturityDayRole = Qt::UserRole + 10;
const int BorderColorRole = Qt::UserRole + 11;
const int PostfixTxtRole = Qt::UserRole + 12;
const int PostfixTxtRectRole = Qt::UserRole + 13;
const int PostfixTxtRectColor = Qt::UserRole + 14;
const int SpecialLabelRole = Qt::UserRole + 15;
const int DataSelIdRole = Qt::UserRole + 16;
const int DataAlignRole = Qt::UserRole + 17;
const int SpecialLabelTextRole = Qt::UserRole + 18;
const int SpecialLabelColorRole = Qt::UserRole + 19;
const int SpecialLabelCommentBeginRole = Qt::UserRole + 20;
const int SpecialLabelCommentEndRole = Qt::UserRole + 29;
const int SpecialLabelCommentColorBeginRole = Qt::UserRole + 30;
const int SpecialLabelCommentColorEndRole = Qt::UserRole + 39;
const int SpecialLabelCommentCountRole = Qt::UserRole + 40;
const int SpecialLabelIdRole = Qt::UserRole + 41;

struct FlashInfo {
  QString id;
  bool entireRow = true;
  std::vector<int> cols;
  int flashCount = -1;

  FlashInfo() = default;
  FlashInfo(const QString& str, bool e = true,
            std::vector<int> s = std::vector<int>(), int c = -1)
      : id(str), entireRow(e), cols(s), flashCount(c) {}
};

class QTableView;
class QScrollBar;
class QAbstractItemDelegate;
class S_WIDGETS_EXPORT DefaulTableItemDelegate : public QStyledItemDelegate {
 public:
  DefaulTableItemDelegate(QObject* p);
  virtual void paint(QPainter* painter, const QStyleOptionViewItem& option,
                     const QModelIndex& index) const override;
};

class S_WIDGETS_EXPORT SVirtualTable : public QWidget {
  Q_OBJECT
  friend class STableColumnSet;

 public:
  SVirtualTable(QWidget* p = nullptr, QHeaderView* header = nullptr);

  QTableView* table() const { return m_table; }
  void setRealDataCount(int c);
  int pageCount() const { return m_pageCount; }
  int sliderPos() const;
  void resetScroll(bool resetPos = false);
  bool isVScrollBarShown() const;
  void addFlashInfo(const FlashInfo& fi, bool startImmediately = true);
  void removeFlashInfo(const FlashInfo& fi);
  void clearTable(bool resetPos = false);
  void startFlash();

  void setHeaderSortable(bool v);
  void lockTable();
  void unlockTable();
  void selectItem(int row);
  void unSelectItem();
  void showLockNewData(const QString& tip);

 protected:
  bool eventFilter(QObject* watched, QEvent* event) override;
  void resizeEvent(QResizeEvent* event) override;
 signals:
  void viewPosChanged(int position);  // 滚动条位置改变
  void headerSort(int col);
  void unlocked();

 protected slots:
  void onTimeOut();
  void onHeaderClicked(int logicalIndex);
  void updateLockGeo();
  void updateSectionWidth(int logicalIndex, int oldSize, int newSize);
  void updateFrozenSectionWidth(int logicalIndex, int oldSize, int newSize);

 private:
  void updateFrozenTableGeometry();
  void setFrozenCols(int cols);  // 最后调用

 private:
  QTableView* m_table = nullptr;
  QScrollBar* m_scrollBar =
      nullptr;  // 垂直滚动条，水平滚动条使用TableView自己的
  QLabel* m_lockIndicator = nullptr;
  int m_realDataCount = 0;
  int m_pageCount = 0;
  QTimer* m_flashTimer = nullptr;
  bool m_headerSortable = false;
  bool m_locked = false;
  QTableView* m_frozenTable = nullptr;
  int m_frozenCols = 0;
};

class S_WIDGETS_EXPORT DefaultTableModel : public QStandardItemModel {
 public:
  DefaultTableModel(QObject* p);
  void setTable(SVirtualTable* t) { m_table = t; }
  QVariant data(const QModelIndex& index,
                int role = Qt::DisplayRole) const override;
  void addFlashInfo(const FlashInfo& fi);
  void removeFlashInfo(const FlashInfo& fi);
  bool flash();

 private:
  SVirtualTable* m_table = nullptr;
  std::map<QString, FlashInfo> m_flashInfos;  // key 为其他类型?
};